#include "Island.h"

Island::Island() : bFog(false), counter(0.0f), fx_m_World(0), fx_m_WorldViewProj(0), fx_m_L_ViewProj(0), fx_tex_shadow_map(0), 
					fx_lights(0), fx_num_lights(0), fx_pEye(0), fx_bShadowed(false), fx_bUsePCSS(false)
{
	isShadowCaster(false);
	isShadowReceiver(true);
}


Island::~Island() 
{
	try
	{
		if (srvSand)
			srvSand->Release();
	}
	catch(...)
	{
		MessageBoxA(0, "exception thrown in  destructor", 0, 0);
	}
}

void Island::draw(const Camera& camera, const vector<Light*>& lights)
{
	ID3DX11EffectScalarVariable* fx_time = getFX()->GetVariableByName("border")->AsScalar();
	fx_time->SetFloat(counter);
	
	// Material
	Mesh::setMaterial(getFX());

	// World Matrix
	XMMATRIX mWorld = XMLoadFloat4x4(&(mtxWorld()));
	fx_m_World->SetMatrix((float*)&mWorld);
	fx_m_WorldViewProj->SetMatrix((float*)&(mWorld * camera.getViewMatrix() * camera.getProjectionMatrix()));
	fx_pEye->SetFloatVector((float*)&(camera.getPosVector3()));

	// Light // mView, shadow_map, light params
	for (unsigned int i=0; i<lights.size(); ++i)
	{
		fx_m_L_ViewProj =	getFX()->GetVariableByName("m_L_ViewProj")->GetElement(i)->AsMatrix();
		fx_lights =			getFX()->GetVariableByName("lights")->GetElement(i);
		fx_tex_shadow_map = getFX()->GetVariableByName("tex_shadow_map")->GetElement(i)->AsShaderResource();
		
		XMMATRIX  m = lights[i]->getViewProjMatrix();
		fx_m_L_ViewProj->SetMatrix(		(float*)&m	);
		fx_tex_shadow_map->SetResource(	lights[i]->getShadowMapSRV())	;
		fx_lights->SetRawValue(	(void*)&(lights[i]->getLightStructure()), 0, sizeof(Light_Params)	);
	}
	ID3DX11EffectScalarVariable*	fx_shadow_size = getFX()->GetVariableByName("shadow_size")->AsScalar();
	fx_shadow_size->SetInt(lights[0]->getShadowMapSize());
	fx_num_lights->SetInt(lights.size());
	
	fx_bShadowed->SetBool(isShadowReceiver());
	fx_bUsePCSS->SetBool(PCSS());

	ID3DX11EffectScalarVariable*  fx_bLit = getFX()->GetVariableByName("bLit")->AsScalar();
	fx_bLit->SetBool(isLit());

	ID3DX11EffectShaderResourceVariable* fx_texSand = getFX()->GetVariableByName("texSand")->AsShaderResource();
	fx_texSand->SetResource(srvSand);

	Mesh::draw(0, getFX(), "Island");


	for (unsigned int i=0; i<lights.size(); ++i) {
		fx_tex_shadow_map = getFX()->GetVariableByName("tex_shadow_map")->GetElement(i)->AsShaderResource();
		fx_tex_shadow_map->SetResource(0);
	}
	ID3DX11EffectTechnique* tech = getFX()->GetTechniqueByName("Island");
	tech->GetPassByIndex(0)->Apply(0, context());
}


void Island::draw(int subset, ID3DX11Effect* fx, const char* technique) const
{
	Mesh::draw(0, fx, technique);


}


void Island::Update(float dt)
{
	if (bFog)
		counter += dt;
}


void Island::init(const char* filename, ID3D11Device* g_device, ID3D11DeviceContext* g_context)
{
	Mesh::init(filename, g_device, g_context);
	createEffect("../Desert_Island/shaders/island.fxo", g_device);



	fx_m_World				= getFX()->GetVariableByName("m_World")->AsMatrix();
	fx_m_WorldViewProj		= getFX()->GetVariableByName("m_WorldViewProj")->AsMatrix();
	fx_m_L_ViewProj			= getFX()->GetVariableByName("m_L_ViewProj")->AsMatrix();

	fx_tex_shadow_map		= getFX()->GetVariableByName("tex_shadow_map")->AsShaderResource();

	fx_lights				= getFX()->GetVariableByName("lights");

	fx_num_lights			= getFX()->GetVariableByName("num_lights")->AsScalar();

	fx_pEye					= getFX()->GetVariableByName("pEye")->AsVector();
	fx_bShadowed			= getFX()->GetVariableByName("bShadowed")->AsScalar();
	fx_bUsePCSS				= getFX()->GetVariableByName("bUsePCSS")->AsScalar();

	HRESULT hr = D3DX11CreateShaderResourceViewFromFile(g_dev(), L"../Desert_island/media/sand3.jpg", 0, 0, &srvSand, 0);
	if (FAILED(hr))
		MessageBoxA(0, "Error creating tree heightmap srv", 0, 0);
}



void Island::startFog()
{
	if (bFog) return;

	bFog = true;
	counter = 0.0f;
}

void Island::reset()
{
	bFog = false;
}